#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
修复三班制排班接口中照护时间线生成逻辑，确保只为老人的实际需求生成时间段
"""

import logging
import json
import uuid
from datetime import datetime, date

from app import db
from app.three_shift import ThreeShiftScheduler
from app.models import ScheduleResult, TimeSlot
from app.new_models import CareGbNursingAction, DigitalEmployeeSkills
from app.model_adapters import ElderdemandAdapter
from app.activity_name_formatter import remove_leading_number

logger = logging.getLogger(__name__)

def get_skill_name_by_nursing_id(nursing_id):
    """根据nursing_id获取digital_employee_skills表中的name字段"""
    if not nursing_id:
        return None

    # 查询digital_employee_skills表
    skill = DigitalEmployeeSkills.query.filter_by(id=nursing_id).first()

    if not skill:
        return None

    # 直接返回技能名称
    return skill.name

def get_skill_name_by_activity_id(activity_id):
    """根据activity_id获取digital_employee_skills表中的name字段

    首先查询care_gb_nursing_action表获取nursing_id，
    然后根据nursing_id查询digital_employee_skills表获取name字段
    """
    if not activity_id:
        return None

    # 查询care_gb_nursing_action表
    action = CareGbNursingAction.query.filter_by(id=activity_id).first()

    if not action or not action.nursing_id:
        return None

    # 获取第一个nursing_id
    nursing_ids = [
        nursing_id.strip()
        for nursing_id in action.nursing_id.split(",")
        if nursing_id.strip()
    ]

    if not nursing_ids:
        return None

    # 查询digital_employee_skills表
    skill = DigitalEmployeeSkills.query.filter_by(id=nursing_ids[0]).first()

    if not skill:
        return None

    # 直接返回技能名称
    return skill.name

def apply_fix_to_three_shift():
    """将照护时间线生成逻辑的修复应用到三班制排班接口"""
    logger.info("=" * 80)
    logger.info("将照护时间线生成逻辑的修复应用到三班制排班接口")
    logger.info("=" * 80)

    # 保存原始方法
    original_generate_and_save_schedule = ThreeShiftScheduler.generate_and_save_schedule

    def improved_generate_and_save_schedule(
        self,
        schedule_type=None,
        num_days=None,
        start_date=None,
        shift_start_time=None,
        generate_care_timeline=None,
        shift_mode=None,
        custom_shifts=None,
        time_slots_per_day=None,
        time_interval_minutes=None,
        day_segments=None,
        first_segment_start=None,
        first_segment_end=None,
        param_priority_enabled=None,
        auto_adjust_time=None,
        use_global_multi_day_params=None,
        current_day_only=None,
    ):
        """改进的生成并保存排班计划方法"""
        # 调用原始方法生成排班计划
        result = original_generate_and_save_schedule(
            self,
            schedule_type=schedule_type,
            num_days=num_days,
            start_date=start_date,
            shift_start_time=shift_start_time,
            generate_care_timeline=generate_care_timeline,
            shift_mode=shift_mode,
            custom_shifts=custom_shifts,
            time_slots_per_day=time_slots_per_day,
            time_interval_minutes=time_interval_minutes,
            day_segments=day_segments,
            first_segment_start=first_segment_start,
            first_segment_end=first_segment_end,
            param_priority_enabled=param_priority_enabled,
            auto_adjust_time=auto_adjust_time,
            use_global_multi_day_params=use_global_multi_day_params,
            current_day_only=current_day_only,
        )

        # 如果不需要生成照护时间线，直接返回结果
        if not generate_care_timeline:
            return result

        # 获取批次号 - 使用单一批次号，避免生成多条记录
        # 从数据库中获取最大批次号
        from app.models import ScheduleResult
        max_batch = db.session.query(db.func.max(ScheduleResult.batch_number)).scalar() or 0

        # 使用传入的批次号或生成新的批次号
        # 检查result是字典还是ScheduleResult对象
        if isinstance(result, dict):
            batch_number = result.get("batch_number")
        else:
            # 如果是ScheduleResult对象，尝试获取batch_number属性
            batch_number = getattr(result, "batch_number", None)

        if not batch_number:
            # 如果没有获取到批次号，使用最大批次号
            # 注意：这里不再自动加1，而是使用当前最大批次号，避免生成多条记录
            batch_number = max_batch
            logger.info(f"使用当前最大批次号: {batch_number}")

        # 获取排班日期 - 始终使用当天日期
        plan_date = date.today()

        # 获取所有老人
        elders = self.get_elders()
        if not elders:
            logger.warning("没有获取到老人信息，无法修复照护时间线")
            return result

        # 获取所有护理员，不限制数量
        from app.model_adapters import CareAttendantskillsAdapter

        # 使用CareAttendantskillsAdapter从app_user和app_user_detail表获取所有护理员
        logger.info("从app_user和app_user_detail表获取所有护理员信息")
        all_caregivers = CareAttendantskillsAdapter.query_all()

        # 使用所有护理员，不限制数量
        caregivers = all_caregivers

        if not caregivers:
            logger.warning("没有获取到护理员信息，无法修复照护时间线")
            return result

        # 确保使用所有符合条件的护理员，而不仅仅是两位
        logger.info(f"获取到 {len(caregivers)} 个护理员，全部用于照护时间线生成")

        # 移除max_caregivers限制，确保使用所有护理员
        self.max_caregivers = None

        # 打印所有护理员的信息，便于调试
        for i, caregiver in enumerate(caregivers):
            logger.info(f"护理员 {i+1}: ID={caregiver.id}, 姓名={caregiver.attendant_name}, 技能={caregiver.skills}")

        # 创建时间段列表
        time_slots = self.time_slots_per_day
        time_interval_minutes = self.time_interval_minutes

        time_slot_list = []
        for i in range(time_slots):
            hours = (i * time_interval_minutes) // 60
            minutes = (i * time_interval_minutes) % 60
            next_hours = ((i + 1) * time_interval_minutes) // 60
            next_minutes = ((i + 1) * time_interval_minutes) % 60

            # 处理跨天的情况
            if next_hours >= 24:
                next_hours -= 24

            time_slot_str = f"{hours:02d}:{minutes:02d}-{next_hours:02d}:{next_minutes:02d}"
            time_slot_list.append(time_slot_str)

        # 获取当前时间
        current_datetime = datetime.now()

        # 为每个老人生成照护时间线
        for elder in elders:
            elder_id = elder.elder
            logger.info(f"为老人 {elder_id} 生成照护时间线")

            # 获取老人的护理需求
            elder_demands = ElderdemandAdapter.query_filter_by(elder=elder_id, arrange="1").all()
            logger.info(f"获取到 {len(elder_demands)} 个护理需求记录")

            # 解析老人的护理动作需求
            action_ids = []
            for demand in elder_demands:
                if demand.actions:
                    action_ids.extend(
                        [
                            int(action_id.strip())
                            for action_id in demand.actions.split(",")
                            if action_id.strip().isdigit()
                        ]
                    )

            logger.info(f"护理动作ID: {action_ids}")

            # 获取护理动作详情
            actions = []
            action_details = {}  # 存储护理动作详情，包括层级名称
            if action_ids:
                actions = CareGbNursingAction.query.filter(CareGbNursingAction.id.in_(action_ids)).all()
                logger.info(f"获取到 {len(actions)} 个护理动作详情")

                # 获取每个护理动作的nursing_id
                for action in actions:

                    # 获取nursing_id列表
                    nursing_ids = []
                    if action.nursing_id:
                        nursing_ids = [
                            nursing_id.strip()
                            for nursing_id in action.nursing_id.split(",")
                            if nursing_id.strip()
                        ]

                    # 获取digital_employee_skills表中的name字段
                    skill_names = []
                    for nursing_id in nursing_ids:
                        skill_name = get_skill_name_by_nursing_id(nursing_id)
                        if skill_name:
                            skill_names.append(skill_name)

                    # 始终使用digital_employee_skills表中的名称
                    # 如果有技能名称，使用技能名称，否则使用固定的默认名称
                    display_name = skill_names[0] if skill_names else "老年人照护活动"
                    logger.info(f"护理动作 ID={action.id} 使用digital_employee_skills表中的名称: {display_name}")

                    # 存储详情
                    action_details[action.id] = {
                        "original_name": action.name,
                        "nursing_ids": nursing_ids,
                        "skill_names": skill_names,
                        "display_name": display_name
                    }

                    logger.info(f"护理动作 ID={action.id}, 原始名称: {action.name}, 护理技能ID: {nursing_ids}, 技能名称: {skill_names}, 显示名称: {display_name}")

            # 创建照护时间线
            care_timeline = []

            # 跟踪护理员的工作负荷
            caregiver_workload = {caregiver.id: 0 for caregiver in caregivers}

            # 创建活动映射，用于快速查找每个时间段对应的活动
            activity_map = {}

            # 定义用餐时间段
            breakfast_time = [(7, 0), (8, 30)]  # 早餐时间: 07:00-08:30
            lunch_time = [(11, 30), (13, 0)]    # 午餐时间: 11:30-13:00
            dinner_time = [(17, 30), (19, 0)]   # 晚餐时间: 17:30-19:00

            # 用餐活动名称和ID
            # 第一段：为老年人打饭
            meal_activity_name_1 = remove_leading_number("为老年人打饭")
            meal_activity_id_1 = "180"  # 为老年人打饭的活动ID

            # 第二段：帮助老年人进食、进水
            meal_activity_name_2 = remove_leading_number("帮助老年人进食、进水")
            meal_activity_id_2 = "5"  # 帮助老年人进食、进水的活动ID

            # 全局变量，用于其他地方引用
            global meal_activity_id, meal_activity_name
            meal_activity_id = meal_activity_id_1  # 兼容旧代码
            meal_activity_name = meal_activity_name_1  # 兼容旧代码

            # 首先处理睡眠和用餐时间段
            sleep_time_slots = []
            meal_time_slots = []
            meal_time_pairs = []  # 存储用餐时间段的配对信息

            # 先解析所有时间段
            time_slot_info = []
            for i, time_slot_str in enumerate(time_slot_list):
                time_parts = time_slot_str.split("-")
                if len(time_parts) == 2:
                    start_time = time_parts[0]
                    start_hour = int(start_time.split(":")[0])
                    start_minute = int(start_time.split(":")[1])

                    # 转换为小时数（带小数）
                    hour_decimal = start_hour + start_minute / 60

                    time_slot_info.append({
                        "index": i,
                        "time_slot_str": time_slot_str,
                        "start_hour": start_hour,
                        "start_minute": start_minute,
                        "hour_decimal": hour_decimal
                    })

            # 处理睡眠时间段
            for info in time_slot_info:
                time_slot_str = info["time_slot_str"]
                start_hour = info["start_hour"]

                # 判断是否是睡眠时间段（22:00-06:00）
                is_sleep_time = (start_hour >= 22) or (start_hour < 6)

                if is_sleep_time:
                    sleep_time_slots.append(time_slot_str)
                    # 获取睡眠观察技能的名称
                    sleep_skill_name = get_skill_name_by_nursing_id("17")  # 睡眠观察技能ID为17
                    sleep_display_name = sleep_skill_name if sleep_skill_name else "老年人睡眠状况观察记录"

                    # 移除开头的数字
                    sleep_display_name = remove_leading_number(sleep_display_name)

                    # 将睡眠活动添加到映射中
                    activity_map[time_slot_str] = {
                        "action_name": sleep_display_name,
                        "action_id": "17",  # 睡眠观察技能ID为17
                        "nursing_ids": ["17"]  # 睡眠观察技能ID为17
                    }
                    logger.info(f"时间段 {time_slot_str} 是睡眠时间段，设置为 {sleep_display_name}")

            # 收集早中晚餐时间段
            breakfast_slots = []
            lunch_slots = []
            dinner_slots = []

            # 收集身体清洁、口腔清洁、仪容仪表修饰和更衣活动的时间段
            body_cleaning_slots = []  # 19:20-21:40 身体清洁 ID: 23
            oral_cleaning_slots = []  # 06:00-07:00 口腔清洁 ID: 20
            grooming_slots = []       # 06:00-07:00 仪容仪表修饰 ID: 24
            changing_clothes_slots = [] # 19:20-21:40 更衣 ID: 25

            # 收集所有可能的用餐时间段
            for i in range(0, len(time_slot_info) - 1, 2):  # 每次处理两个连续的时间段
                first_slot = time_slot_info[i]
                second_slot = time_slot_info[i + 1]

                first_time_str = first_slot["time_slot_str"]
                second_time_str = second_slot["time_slot_str"]

                start_hour = first_slot["start_hour"]
                start_minute = first_slot["start_minute"]
                hour_decimal = first_slot["hour_decimal"]

                # 判断是否是早餐时间段
                is_breakfast_time = (breakfast_time[0][0] <= start_hour < breakfast_time[1][0]) or \
                                   (start_hour == breakfast_time[0][0] and start_minute >= breakfast_time[0][1]) or \
                                   (start_hour == breakfast_time[1][0] and start_minute < breakfast_time[1][1])

                # 判断是否是午餐时间段
                is_lunch_time = (lunch_time[0][0] <= start_hour < lunch_time[1][0]) or \
                               (start_hour == lunch_time[0][0] and start_minute >= lunch_time[0][1]) or \
                               (start_hour == lunch_time[1][0] and start_minute < lunch_time[1][1])

                # 判断是否是晚餐时间段
                is_dinner_time = (dinner_time[0][0] <= start_hour < dinner_time[1][0]) or \
                                (start_hour == dinner_time[0][0] and start_minute >= dinner_time[0][1]) or \
                                (start_hour == dinner_time[1][0] and start_minute < dinner_time[1][1])

                # 判断是否是身体清洁时间段（19:20-21:40）
                is_body_cleaning_time = (19 <= start_hour < 21) or \
                                       (start_hour == 21 and start_minute < 40)

                # 判断是否是口腔清洁和仪容仪表修饰时间段（06:00-07:00）
                is_oral_grooming_time = (start_hour == 6)

                # 如果是用餐时间段，且不是睡眠时间段，且两个时间段都不在睡眠时间段内
                if first_time_str not in sleep_time_slots and second_time_str not in sleep_time_slots:
                    if is_breakfast_time:
                        breakfast_slots.append((first_time_str, second_time_str))
                    elif is_lunch_time:
                        lunch_slots.append((first_time_str, second_time_str))
                    elif is_dinner_time:
                        dinner_slots.append((first_time_str, second_time_str))

                # 收集身体清洁时间段（19:20-21:40）
                if is_body_cleaning_time and first_time_str not in sleep_time_slots:
                    body_cleaning_slots.append(first_time_str)

                # 收集更衣时间段（19:20-21:40）
                if is_body_cleaning_time and first_time_str not in sleep_time_slots:
                    changing_clothes_slots.append(first_time_str)

                # 收集口腔清洁和仪容仪表修饰时间段（06:00-07:00）
                if is_oral_grooming_time and first_time_str not in sleep_time_slots:
                    # 口腔清洁和仪容仪表修饰时间段分开收集，确保不会重复
                    oral_cleaning_slots.append(first_time_str)
                    # 仪容仪表修饰时间段与口腔清洁时间段分开
                    grooming_slots.append(first_time_str)

                # 确保收集到足够的时间段
                if len(oral_cleaning_slots) < 10:
                    if first_time_str not in sleep_time_slots and first_time_str not in oral_cleaning_slots:
                        oral_cleaning_slots.append(first_time_str)

                if len(grooming_slots) < 10:
                    if first_time_str not in sleep_time_slots and first_time_str not in grooming_slots:
                        grooming_slots.append(first_time_str)

            # 为每位老人随机分配早中晚餐时间段
            import random

            # 随机选择早餐时间段（如果有）
            if breakfast_slots:
                breakfast_pair = random.choice(breakfast_slots)
                first_time_str, second_time_str = breakfast_pair

                # 将两个连续的时间段都添加到用餐时间段列表中
                meal_time_slots.append(first_time_str)
                meal_time_slots.append(second_time_str)

                # 记录这两个时间段是一对
                meal_time_pairs.append((first_time_str, second_time_str))

                # 将用餐活动添加到映射中（第一个时间段设置为"为老年人打饭"，第二个时间段设置为"帮助老年人进食、进水"）
                activity_map[first_time_str] = {
                    "action_name": meal_activity_name_1,
                    "action_id": meal_activity_id_1,
                    "nursing_ids": []  # 用餐活动不需要特定技能
                }

                activity_map[second_time_str] = {
                    "action_name": meal_activity_name_2,
                    "action_id": meal_activity_id_2,
                    "nursing_ids": []  # 用餐活动不需要特定技能
                }

                logger.info(f"为老人随机分配早餐时间段: {first_time_str} 设置为 {meal_activity_name_1}，{second_time_str} 设置为 {meal_activity_name_2}（共40分钟）")

            # 随机选择午餐时间段（如果有）
            if lunch_slots:
                lunch_pair = random.choice(lunch_slots)
                first_time_str, second_time_str = lunch_pair

                # 将两个连续的时间段都添加到用餐时间段列表中
                meal_time_slots.append(first_time_str)
                meal_time_slots.append(second_time_str)

                # 记录这两个时间段是一对
                meal_time_pairs.append((first_time_str, second_time_str))

                # 将用餐活动添加到映射中（第一个时间段设置为"为老年人打饭"，第二个时间段设置为"帮助老年人进食、进水"）
                activity_map[first_time_str] = {
                    "action_name": meal_activity_name_1,
                    "action_id": meal_activity_id_1,
                    "nursing_ids": []  # 用餐活动不需要特定技能
                }

                activity_map[second_time_str] = {
                    "action_name": meal_activity_name_2,
                    "action_id": meal_activity_id_2,
                    "nursing_ids": []  # 用餐活动不需要特定技能
                }

                logger.info(f"为老人随机分配午餐时间段: {first_time_str} 设置为 {meal_activity_name_1}，{second_time_str} 设置为 {meal_activity_name_2}（共40分钟）")

            # 随机选择晚餐时间段（如果有）
            if dinner_slots:
                dinner_pair = random.choice(dinner_slots)
                first_time_str, second_time_str = dinner_pair

                # 将两个连续的时间段都添加到用餐时间段列表中
                meal_time_slots.append(first_time_str)
                meal_time_slots.append(second_time_str)

                # 记录这两个时间段是一对
                meal_time_pairs.append((first_time_str, second_time_str))

                # 将用餐活动添加到映射中（第一个时间段设置为"为老年人打饭"，第二个时间段设置为"帮助老年人进食、进水"）
                activity_map[first_time_str] = {
                    "action_name": meal_activity_name_1,
                    "action_id": meal_activity_id_1,
                    "nursing_ids": []  # 用餐活动不需要特定技能
                }

                activity_map[second_time_str] = {
                    "action_name": meal_activity_name_2,
                    "action_id": meal_activity_id_2,
                    "nursing_ids": []  # 用餐活动不需要特定技能
                }

                logger.info(f"为老人随机分配晚餐时间段: {first_time_str} 设置为 {meal_activity_name_1}，{second_time_str} 设置为 {meal_activity_name_2}（共40分钟）")

            # 随机选择身体清洁时间段（19:20-21:40）
            if body_cleaning_slots:
                # 随机选择一个时间段
                body_cleaning_slot = random.choice(body_cleaning_slots)

                # 将身体清洁活动添加到映射中
                activity_map[body_cleaning_slot] = {
                    "action_name": "身体清洁",
                    "action_id": "23",
                    "nursing_ids": []  # 不需要特定技能
                }

                logger.info(f"为老人随机分配身体清洁时间段: {body_cleaning_slot} 设置为 身体清洁（ID: 23）")

            # 随机选择更衣时间段（19:20-21:40）
            if changing_clothes_slots:
                # 过滤掉已分配的时间段
                available_slots = [slot for slot in changing_clothes_slots if slot not in activity_map]

                if available_slots:
                    # 随机选择一个时间段
                    changing_clothes_slot = random.choice(available_slots)

                    # 将更衣活动添加到映射中
                    activity_map[changing_clothes_slot] = {
                        "action_name": "为老年人更衣",
                        "action_id": "25",
                        "nursing_ids": []  # 不需要特定技能
                    }

                    logger.info(f"为老人随机分配更衣时间段: {changing_clothes_slot} 设置为 为老年人更衣（ID: 25）")

            # 直接选择一个非睡眠时间段作为口腔清洁时间段
            oral_cleaning_slot = None

            # 优先选择06:00-07:00范围内的时间段
            for slot_info in time_slot_info:
                slot_time_str = slot_info["time_slot_str"]
                start_hour = slot_info["start_hour"]

                if start_hour == 6 and slot_time_str not in sleep_time_slots and slot_time_str not in activity_map:
                    oral_cleaning_slot = slot_time_str
                    break

            # 如果没有找到06:00-07:00范围内的可用时间段，选择任意非睡眠时间段
            if not oral_cleaning_slot:
                for slot_info in time_slot_info:
                    slot_time_str = slot_info["time_slot_str"]
                    if slot_time_str not in sleep_time_slots and slot_time_str not in activity_map:
                        oral_cleaning_slot = slot_time_str
                        break

            # 如果仍然没有找到，强制选择一个非睡眠时间段（即使已经被分配）
            if not oral_cleaning_slot:
                for slot_info in time_slot_info:
                    slot_time_str = slot_info["time_slot_str"]
                    if slot_time_str not in sleep_time_slots:
                        oral_cleaning_slot = slot_time_str
                        break

            # 如果找到了时间段，强制分配口腔清洁活动
            if oral_cleaning_slot:
                # 将口腔清洁活动添加到映射中，覆盖原有活动
                activity_map[oral_cleaning_slot] = {
                    "action_name": "为老年人清洁口腔",
                    "action_id": "20",
                    "nursing_ids": []  # 不需要特定技能
                }

                logger.info(f"为老人强制分配口腔清洁时间段: {oral_cleaning_slot} 设置为 为老年人清洁口腔（ID: 20）")
            else:
                logger.warning("没有找到可用的口腔清洁时间段，甚至没有非睡眠时间段")

            # 直接选择一个非睡眠时间段作为仪容仪表修饰时间段（不同于口腔清洁时间段）
            grooming_slot = None

            # 优先选择06:00-07:00范围内的时间段
            for slot_info in time_slot_info:
                slot_time_str = slot_info["time_slot_str"]
                start_hour = slot_info["start_hour"]

                if start_hour == 6 and slot_time_str not in sleep_time_slots and slot_time_str != oral_cleaning_slot:
                    grooming_slot = slot_time_str
                    break

            # 如果没有找到06:00-07:00范围内的可用时间段，选择任意非睡眠时间段
            if not grooming_slot:
                for slot_info in time_slot_info:
                    slot_time_str = slot_info["time_slot_str"]
                    if slot_time_str not in sleep_time_slots and slot_time_str != oral_cleaning_slot:
                        grooming_slot = slot_time_str
                        break

            # 如果仍然没有找到，强制选择一个非睡眠时间段（即使已经被分配）
            if not grooming_slot:
                # 最后尝试任意非睡眠时间段
                for slot_info in time_slot_info:
                    slot_time_str = slot_info["time_slot_str"]
                    if slot_time_str not in sleep_time_slots and slot_time_str != oral_cleaning_slot:
                        grooming_slot = slot_time_str
                        break

            # 如果找到了时间段，强制分配仪容仪表修饰活动
            if grooming_slot:
                # 将仪容仪表修饰活动添加到映射中，覆盖原有活动
                activity_map[grooming_slot] = {
                    "action_name": "为老年人修饰仪容仪表",
                    "action_id": "24",
                    "nursing_ids": []  # 不需要特定技能
                }

                logger.info(f"为老人强制分配仪容仪表修饰时间段: {grooming_slot} 设置为 为老年人修饰仪容仪表（ID: 24）")
            else:
                logger.warning("没有找到可用的仪容仪表修饰时间段，甚至没有非睡眠时间段")

            # 如果有护理需求，处理这些需求
            if actions:
                logger.info(f"老人 {elder_id} 有 {len(actions)} 个护理需求")

                # 为每个护理需求分配一个时间段（跳过已分配的睡眠时间段）
                action_index = 0
                for i, time_slot_str in enumerate(time_slot_list):
                    # 如果已经是睡眠时间段，跳过
                    if time_slot_str in sleep_time_slots:
                        continue

                    # 如果已经处理完所有护理需求，跳出循环
                    if action_index >= len(actions):
                        break

                    action = actions[action_index]
                    action_id = action.id

                    # 始终使用digital_employee_skills表中的名称
                    action_detail = action_details.get(action_id, {})

                    # 首先尝试从action_detail中获取display_name
                    action_name = action_detail.get("display_name")

                    # 如果没有display_name，尝试使用get_skill_name_by_activity_id函数获取
                    if not action_name:
                        action_name = get_skill_name_by_activity_id(action_id)

                    # 如果仍然没有找到名称，使用特定的名称映射或默认名称
                    if not action_name:
                        # 为特定的活动ID提供更有意义的名称
                        activity_name_map = {
                            "32": "进食能力：独立使用餐具",
                            "37": "进食能力：独立完成",
                            "42": "饮水能力：独立完成",
                            "47": "口腔清洁能力：独立完成",
                            "52": "面部清洁能力：独立完成",
                            "57": "排尿控制能力：自行控制",
                            "62": "排便控制能力：自行控制",
                            "67": "如厕能力：独立完成",
                            "72": "穿脱衣服能力：独立完成",
                            "77": "穿脱鞋袜能力：独立完成",
                            "82": "平地行走能力：独立行走",
                            "87": "上下楼梯能力：独立完成"
                        }

                        # 如果活动ID在映射中，使用映射的名称
                        if action_id in activity_name_map:
                            action_name = activity_name_map[action_id]
                            logger.info(f"为活动ID={action_id}使用特定的名称映射: {action_name}")
                        else:
                            # 否则使用默认名称
                            action_name = "老年人照护活动"
                            logger.warning(f"无法为活动ID={action_id}找到digital_employee_skills表中的名称，使用默认名称: {action_name}")

                    nursing_ids = action_detail.get("nursing_ids", [])
                    logger.info(f"为活动ID={action_id}使用名称: {action_name}")

                    # 将活动添加到映射中，覆盖可能存在的用餐活动
                    # 这样确保老人需求优先于固定的用餐活动
                    activity_map[time_slot_str] = {
                        "action_name": action_name,
                        "action_id": action_id,
                        "nursing_ids": nursing_ids
                    }

                    action_index += 1

                    # 如果覆盖了用餐时间段，记录日志
                    if time_slot_str in meal_time_slots:
                        # 检查是否是成对用餐时间段的一部分
                        is_part_of_pair = False
                        pair_partner = None

                        for pair in meal_time_pairs:
                            if time_slot_str in pair:
                                is_part_of_pair = True
                                # 找到配对的另一个时间段
                                pair_partner = pair[0] if time_slot_str == pair[1] else pair[1]
                                break

                        if is_part_of_pair and pair_partner in meal_time_slots:
                            # 如果是成对用餐时间段的一部分，且配对的时间段也在用餐时间段列表中
                            # 则将配对的时间段也设置为老人需求，以保持连续性
                            logger.info(f"为时间段 {time_slot_str} 分配护理需求: {action_name} (ID: {action_id})，覆盖了用餐活动")
                            logger.info(f"同时为配对的用餐时间段 {pair_partner} 也分配相同的护理需求，以保持连续性")
                        else:
                            logger.info(f"为时间段 {time_slot_str} 分配护理需求: {action_name} (ID: {action_id})，覆盖了用餐活动")
                    else:
                        logger.info(f"为时间段 {time_slot_str} 分配护理需求: {action_name} (ID: {action_id})")

            # 创建用餐时间段组和对应的护理员映射
            meal_groups = []
            current_meal_group = []

            # 首先，将所有连续的用餐时间段分组
            for i, time_slot_str in enumerate(time_slot_list):
                if time_slot_str in activity_map and (activity_map[time_slot_str]["action_id"] == meal_activity_id_1 or activity_map[time_slot_str]["action_id"] == meal_activity_id_2):
                    # 如果当前时间段是用餐活动（为老年人打饭或帮助老年人进食、进水）
                    if not current_meal_group:
                        # 如果当前组为空，创建新组
                        current_meal_group = [time_slot_str]
                    else:
                        # 检查是否与上一个时间段连续
                        last_slot = current_meal_group[-1]
                        last_end_time = last_slot.split('-')[1]
                        current_start_time = time_slot_str.split('-')[0]

                        if last_end_time == current_start_time:
                            # 如果连续，添加到当前组
                            current_meal_group.append(time_slot_str)
                        else:
                            # 如果不连续，保存当前组并创建新组
                            if len(current_meal_group) > 0:
                                meal_groups.append(current_meal_group)
                            current_meal_group = [time_slot_str]
                else:
                    # 如果当前时间段不是用餐活动，保存当前组
                    if len(current_meal_group) > 0:
                        meal_groups.append(current_meal_group)
                        current_meal_group = []

            # 保存最后一个组
            if len(current_meal_group) > 0:
                meal_groups.append(current_meal_group)

            # 为每个用餐时间段组分配同一个护理员
            meal_group_caregivers = {}
            for group_index, group in enumerate(meal_groups):
                if len(group) > 0:
                    logger.info(f"用餐时间段组 {group_index+1}: {group}")

                    # 匹配护理员
                    matched_caregivers = []

                    # 记录日志
                    logger.info("为用餐时间段组匹配护理员")

                    for caregiver in caregivers:
                        # 解析护理员技能
                        caregiver_skills = []
                        if caregiver.skills:
                            caregiver_skills = [
                                skill.strip()
                                for skill in caregiver.skills.split(",")
                                if skill.strip()
                            ]

                        # 用餐活动不需要特定技能
                        if caregiver_skills:
                            matched_caregivers.append(caregiver)
                            logger.info(f"护理员 {caregiver.attendant_name} 匹配通用技能")

                    if matched_caregivers:
                        # 根据工作负荷选择护理员
                        matched_caregivers.sort(key=lambda c: caregiver_workload[c.id])
                        selected_caregiver = matched_caregivers[0]

                        # 更新护理员工作负荷（按组内时间段数量增加）
                        caregiver_workload[selected_caregiver.id] += len(group)

                        # 保存该组的护理员信息
                        meal_group_caregivers[group_index] = {
                            "name": selected_caregiver.attendant_name,
                            "id": selected_caregiver.id
                        }

                        logger.info(f"为用餐时间段组 {group_index+1} 分配护理员 {selected_caregiver.attendant_name}")
                    else:
                        logger.warning(f"没有匹配的护理员执行用餐活动组 {group_index+1}")

            # 为所有时间段生成照护时间线
            for time_slot_str in time_slot_list:
                # 检查是否有该时间段的活动
                if time_slot_str in activity_map:
                    action_info = activity_map[time_slot_str]
                    action_name = action_info["action_name"]
                    action_id = action_info["action_id"]
                    nursing_ids = action_info["nursing_ids"]

                    # 检查是否是用餐活动（为老年人打饭或帮助老年人进食、进水）
                    is_meal_activity = action_id == meal_activity_id_1 or action_id == meal_activity_id_2

                    # 如果是用餐活动，查找所属的组
                    if is_meal_activity:
                        group_index = None
                        for i, group in enumerate(meal_groups):
                            if time_slot_str in group:
                                group_index = i
                                break

                        # 如果找到所属的组，且该组已分配护理员
                        if group_index is not None and group_index in meal_group_caregivers:
                            caregiver_info = meal_group_caregivers[group_index]

                            care_timeline.append({
                                "Activity": remove_leading_number(action_name),
                                "TimeSlot": time_slot_str,
                                "Caregiver": caregiver_info["name"],
                                "ActivityId": str(action_id),
                                "CaregiverId": caregiver_info["id"]
                            })

                            logger.info(f"为老人 {elder_id} 在时间段 {time_slot_str} 分配用餐时间段组 {group_index+1} 的护理员 {caregiver_info['name']} 执行用餐活动")
                            continue

                    # 如果不是用餐活动或没有找到所属的组，正常匹配护理员
                    matched_caregivers = []

                    # 记录日志
                    logger.info(f"需要匹配的护理技能ID: {nursing_ids}")

                    for caregiver in caregivers:
                        # 解析护理员技能
                        caregiver_skills = []
                        if caregiver.skills:
                            caregiver_skills = [
                                skill.strip()
                                for skill in caregiver.skills.split(",")
                                if skill.strip()
                            ]

                        # 检查是否匹配
                        if not nursing_ids:
                            # 如果护理动作没有指定技能要求，检查护理员是否有任何技能
                            if caregiver_skills:
                                matched_caregivers.append(caregiver)
                                logger.info(f"护理员 {caregiver.attendant_name} 匹配通用技能")
                        else:
                            # 如果护理动作指定了技能要求，检查护理员是否具备这些技能
                            matched_skills = [skill for skill in nursing_ids if skill in caregiver_skills]
                            if matched_skills:
                                matched_caregivers.append(caregiver)
                                logger.info(f"护理员 {caregiver.attendant_name} 匹配技能: {matched_skills}")

                    if matched_caregivers:
                        # 根据工作负荷选择护理员
                        matched_caregivers.sort(key=lambda c: caregiver_workload[c.id])
                        selected_caregiver = matched_caregivers[0]

                        # 更新护理员工作负荷
                        caregiver_workload[selected_caregiver.id] += 1

                        care_timeline.append({
                            "Activity": remove_leading_number(action_name),
                            "TimeSlot": time_slot_str,
                            "Caregiver": selected_caregiver.attendant_name,
                            "ActivityId": str(action_id),
                            "CaregiverId": selected_caregiver.id
                        })

                        logger.info(f"为老人 {elder_id} 在时间段 {time_slot_str} 分配护理员 {selected_caregiver.attendant_name} 执行活动 {action_name}")
                    else:
                        # 没有匹配的护理员，使用lack
                        care_timeline.append({
                            "Activity": remove_leading_number(action_name),
                            "TimeSlot": time_slot_str,
                            "Caregiver": "lack",
                            "ActivityId": str(action_id),
                            "CaregiverId": "-1"
                        })

                        logger.info(f"为老人 {elder_id} 在时间段 {time_slot_str} 没有匹配的护理员执行活动 {action_name}")
                else:
                    # 没有该时间段的活动，使用None
                    care_timeline.append({
                        "TimeSlot": time_slot_str,
                        "Activity": "None",
                        "ActivityId": "0",
                        "Caregiver": "None",
                        "CaregiverId": "0"
                    })

            # 删除该老人的所有现有记录
            existing_results = ScheduleResult.query.filter_by(
                elder=elder_id
            ).all()

            if existing_results:
                logger.info(f"找到老人 {elder_id} 的 {len(existing_results)} 条现有记录，删除所有记录")
                for result in existing_results:
                    db.session.delete(result)

                # 删除该老人的所有时间段记录
                TimeSlot.query.filter_by(
                    elder=elder_id
                ).delete()

                logger.info(f"已删除老人 {elder_id} 的所有现有记录和时间段记录")

            # 强制添加固定活动
            care_timeline = force_add_fixed_activities(care_timeline, time_slot_list, sleep_time_slots, meal_time_slots, caregivers, caregiver_workload)

            # 创建新记录
            logger.info(f"为老人 {elder_id} 创建新的照护计划记录")
            schedule_result = ScheduleResult(
                id=str(uuid.uuid4()),
                elder=elder_id,
                schedule_date=current_datetime,
                schedule_data=care_timeline,  # 直接使用Python对象，SQLAlchemy会自动序列化
                plan_date=plan_date,
                batch_number=batch_number,
                create_time=current_datetime,
                update_time=current_datetime,
                status="active"
            )
            db.session.add(schedule_result)

            # 提交更改
            db.session.flush()

            # 检查是否需要隐藏未分配活动
            from config_params import three_shift_params
            hide_unassigned = three_shift_params.get("hide_unassigned_activities", False)

            # 如果启用了隐藏未分配活动的功能，先过滤掉未分配活动
            if hide_unassigned:
                filtered_timeline = []
                for entry in care_timeline:
                    if entry["Caregiver"] != "None":
                        filtered_timeline.append(entry)
                    else:
                        logger.info(f"预过滤未分配活动: {entry['TimeSlot']} - {entry['Activity']}")

                # 如果过滤后没有任何条目，使用原始条目
                if not filtered_timeline:
                    logger.warning("过滤后没有任何条目，使用原始条目")
                    filtered_timeline = care_timeline
                else:
                    logger.info(f"预过滤后的照护时间线包含 {len(filtered_timeline)} 个时间段（原 {len(care_timeline)} 个）")
                    care_timeline = filtered_timeline

            # 添加查房活动
            logger.info("开始添加查房活动...")
            care_timeline = add_ward_rounds(care_timeline, time_slot_list, sleep_time_slots, meal_time_slots)
            logger.info("查房活动添加完成")

            # 保存时间段记录
            time_slots_to_add = []
            filtered_timeline = []

            for i, entry in enumerate(care_timeline):
                # 如果启用了隐藏未分配活动的功能，且当前活动未分配护理员，则跳过
                if hide_unassigned and entry["Caregiver"] == "None":
                    logger.info(f"隐藏未分配活动: {entry['TimeSlot']} - {entry['Activity']}")
                    continue

                # 添加到过滤后的时间线
                filtered_timeline.append(entry)

                # 创建时间段记录
                time_slot = TimeSlot(
                    id=str(uuid.uuid4()),
                    schedule_result_id=schedule_result.id,
                    elder=elder_id,
                    time_slot=entry["TimeSlot"],
                    activity=entry["Activity"],
                    activity_id=entry["ActivityId"],
                    caregiver=entry["Caregiver"],
                    caregiver_id=entry["CaregiverId"],
                    time_order=i,
                    schedule_date=current_datetime,
                    plan_date=plan_date,
                    batch_number=batch_number,
                    create_time=current_datetime,
                    update_time=current_datetime,
                    status="active"
                )
                time_slots_to_add.append(time_slot)

            # 更新照护计划总表中的数据
            if hide_unassigned:
                schedule_result.schedule_data = filtered_timeline
                logger.info(f"过滤后的照护时间线包含 {len(filtered_timeline)} 个时间段（原 {len(care_timeline)} 个）")
            else:
                schedule_result.schedule_data = care_timeline

            # 批量保存时间段记录
            db.session.bulk_save_objects(time_slots_to_add)

            logger.info(f"为老人 {elder_id} 保存了 {len(time_slots_to_add)} 个时间段记录")

        # 提交事务
        db.session.commit()

        return result

    # 替换方法
    ThreeShiftScheduler.generate_and_save_schedule = improved_generate_and_save_schedule

    logger.info("修复已应用到三班制排班接口")

    return True

def force_add_fixed_activities(care_timeline, time_slot_list, sleep_time_slots, meal_time_slots, caregivers, caregiver_workload):
    """强制添加固定活动到照护计划中

    Args:
        care_timeline: 照护时间线
        time_slot_list: 时间段列表
        sleep_time_slots: 睡眠时间段列表
        meal_time_slots: 用餐时间段列表
        caregivers: 护理员列表
        caregiver_workload: 护理员工作负荷字典

    Returns:
        更新后的照护时间线
    """
    import random

    # 创建时间段与照护时间线条目的映射
    timeline_map = {entry["TimeSlot"]: entry for entry in care_timeline}

    # 解析所有时间段
    time_slot_info = []
    for i, time_slot_str in enumerate(time_slot_list):
        time_parts = time_slot_str.split("-")
        if len(time_parts) == 2:
            start_time = time_parts[0]
            start_hour = int(start_time.split(":")[0])
            start_minute = int(start_time.split(":")[1])

            # 转换为小时数（带小数）
            hour_decimal = start_hour + start_minute / 60

            time_slot_info.append({
                "index": i,
                "time_slot_str": time_slot_str,
                "start_hour": start_hour,
                "start_minute": start_minute,
                "hour_decimal": hour_decimal
            })

    # 1. 强制添加口腔清洁活动（06:00-07:00）
    oral_cleaning_slot = None

    # 优先选择06:00-07:00范围内的时间段
    for slot_info in time_slot_info:
        slot_time_str = slot_info["time_slot_str"]
        start_hour = slot_info["start_hour"]

        if start_hour == 6 and slot_time_str not in sleep_time_slots:
            oral_cleaning_slot = slot_time_str
            break

    # 如果没有找到06:00-07:00范围内的时间段，选择任意非睡眠时间段
    if not oral_cleaning_slot:
        for slot_info in time_slot_info:
            slot_time_str = slot_info["time_slot_str"]
            if slot_time_str not in sleep_time_slots:
                oral_cleaning_slot = slot_time_str
                break

    # 如果找到了时间段，强制分配口腔清洁活动
    if oral_cleaning_slot:
        # 匹配护理员
        matched_caregivers = []
        for caregiver in caregivers:
            # 解析护理员技能
            caregiver_skills = []
            if caregiver.skills:
                caregiver_skills = [
                    skill.strip()
                    for skill in caregiver.skills.split(",")
                    if skill.strip()
                ]

            # 口腔清洁活动不需要特定技能
            if caregiver_skills:
                matched_caregivers.append(caregiver)
                logger.info(f"护理员 {caregiver.attendant_name} 匹配通用技能")

        if matched_caregivers:
            # 根据工作负荷选择护理员
            matched_caregivers.sort(key=lambda c: caregiver_workload[c.id])
            selected_caregiver = matched_caregivers[0]

            # 更新护理员工作负荷
            caregiver_workload[selected_caregiver.id] += 1

            # 将口腔清洁活动添加到映射中，覆盖原有活动
            timeline_map[oral_cleaning_slot] = {
                "Activity": "为老年人清洁口腔",
                "TimeSlot": oral_cleaning_slot,
                "Caregiver": selected_caregiver.attendant_name,
                "ActivityId": "20",
                "CaregiverId": selected_caregiver.id
            }

            logger.info(f"强制分配口腔清洁活动到时间段 {oral_cleaning_slot}，护理员: {selected_caregiver.attendant_name}")
        else:
            # 没有匹配的护理员，使用lack
            timeline_map[oral_cleaning_slot] = {
                "Activity": "为老年人清洁口腔",
                "TimeSlot": oral_cleaning_slot,
                "Caregiver": "lack",
                "ActivityId": "20",
                "CaregiverId": "-1"
            }

            logger.info(f"强制分配口腔清洁活动到时间段 {oral_cleaning_slot}，护理员: lack")

    # 2. 强制添加仪容仪表修饰活动（06:00-07:00）
    grooming_slot = None

    # 优先选择06:00-07:00范围内的时间段（不同于口腔清洁时间段）
    for slot_info in time_slot_info:
        slot_time_str = slot_info["time_slot_str"]
        start_hour = slot_info["start_hour"]

        if start_hour == 6 and slot_time_str not in sleep_time_slots and slot_time_str != oral_cleaning_slot:
            grooming_slot = slot_time_str
            break

    # 如果没有找到06:00-07:00范围内的时间段，选择任意非睡眠时间段（不同于口腔清洁时间段）
    if not grooming_slot:
        for slot_info in time_slot_info:
            slot_time_str = slot_info["time_slot_str"]
            if slot_time_str not in sleep_time_slots and slot_time_str != oral_cleaning_slot:
                grooming_slot = slot_time_str
                break

    # 如果找到了时间段，强制分配仪容仪表修饰活动
    if grooming_slot:
        # 匹配护理员
        matched_caregivers = []
        for caregiver in caregivers:
            # 解析护理员技能
            caregiver_skills = []
            if caregiver.skills:
                caregiver_skills = [
                    skill.strip()
                    for skill in caregiver.skills.split(",")
                    if skill.strip()
                ]

            # 仪容仪表修饰活动不需要特定技能
            if caregiver_skills:
                matched_caregivers.append(caregiver)
                logger.info(f"护理员 {caregiver.attendant_name} 匹配通用技能")

        if matched_caregivers:
            # 根据工作负荷选择护理员
            matched_caregivers.sort(key=lambda c: caregiver_workload[c.id])
            selected_caregiver = matched_caregivers[0]

            # 更新护理员工作负荷
            caregiver_workload[selected_caregiver.id] += 1

            # 将仪容仪表修饰活动添加到映射中，覆盖原有活动
            timeline_map[grooming_slot] = {
                "Activity": "为老年人修饰仪容仪表",
                "TimeSlot": grooming_slot,
                "Caregiver": selected_caregiver.attendant_name,
                "ActivityId": "24",
                "CaregiverId": selected_caregiver.id
            }

            logger.info(f"强制分配仪容仪表修饰活动到时间段 {grooming_slot}，护理员: {selected_caregiver.attendant_name}")
        else:
            # 没有匹配的护理员，使用lack
            timeline_map[grooming_slot] = {
                "Activity": "为老年人修饰仪容仪表",
                "TimeSlot": grooming_slot,
                "Caregiver": "lack",
                "ActivityId": "24",
                "CaregiverId": "-1"
            }

            logger.info(f"强制分配仪容仪表修饰活动到时间段 {grooming_slot}，护理员: lack")

    # 3. 在13:20-19:40时间范围内随机分配指定活动
    # 定义需要分配的活动
    activities_to_assign = [
        {"name": "教老年人手工活动", "id": "40"},
        {"name": "为老年人示范娱乐游戏活动", "id": "41"},
        {"name": "老年人热水袋的应用", "id": "32"},
        {"name": "老年人湿热敷的应用", "id": "33"}
    ]

    # 找出13:20-19:40时间范围内的所有时间段
    afternoon_slots = []
    for slot_info in time_slot_info:
        slot_time_str = slot_info["time_slot_str"]
        start_hour = slot_info["start_hour"]
        start_minute = slot_info["start_minute"]

        # 计算小时数（带小数）
        hour_decimal = start_hour + start_minute / 60

        # 判断是否在13:20-19:40范围内
        if 13.33 <= hour_decimal < 19.67 and slot_time_str not in sleep_time_slots:
            # 不排除用餐时间段，但在日志中记录
            if slot_time_str in meal_time_slots:
                logger.info(f"时间段 {slot_time_str} 是用餐时间段，但仍然添加到下午时间段列表中")
            afternoon_slots.append(slot_time_str)

    # 如果找到了足够的时间段，随机分配活动
    if len(afternoon_slots) >= len(activities_to_assign):
        # 随机打乱时间段列表
        random.shuffle(afternoon_slots)

        # 为每个活动分配一个时间段
        for i, activity in enumerate(activities_to_assign):
            activity_slot = afternoon_slots[i]

            # 匹配护理员
            matched_caregivers = []
            for caregiver in caregivers:
                # 解析护理员技能
                caregiver_skills = []
                if caregiver.skills:
                    caregiver_skills = [
                        skill.strip()
                        for skill in caregiver.skills.split(",")
                        if skill.strip()
                    ]

                # 这些活动不需要特定技能
                if caregiver_skills:
                    matched_caregivers.append(caregiver)
                    logger.info(f"护理员 {caregiver.attendant_name} 匹配通用技能")

            if matched_caregivers:
                # 根据工作负荷选择护理员
                matched_caregivers.sort(key=lambda c: caregiver_workload[c.id])
                selected_caregiver = matched_caregivers[0]

                # 更新护理员工作负荷
                caregiver_workload[selected_caregiver.id] += 1

                # 将活动添加到映射中，覆盖原有活动
                timeline_map[activity_slot] = {
                    "Activity": activity["name"],
                    "TimeSlot": activity_slot,
                    "Caregiver": selected_caregiver.attendant_name,
                    "ActivityId": activity["id"],
                    "CaregiverId": selected_caregiver.id
                }

                logger.info(f"在13:20-19:40时间范围内分配活动 {activity['name']} (ID: {activity['id']}) 到时间段 {activity_slot}，护理员: {selected_caregiver.attendant_name}")
            else:
                # 没有匹配的护理员，使用lack
                timeline_map[activity_slot] = {
                    "Activity": activity["name"],
                    "TimeSlot": activity_slot,
                    "Caregiver": "lack",
                    "ActivityId": activity["id"],
                    "CaregiverId": "-1"
                }

                logger.info(f"在13:20-19:40时间范围内分配活动 {activity['name']} (ID: {activity['id']}) 到时间段 {activity_slot}，护理员: lack")
    else:
        logger.warning(f"在13:20-19:40时间范围内找到的时间段数量 ({len(afternoon_slots)}) 不足以分配所有指定活动 ({len(activities_to_assign)})")

    # 4. 在早上7:00-8:40时间范围内随机分配指定活动
    # 定义需要分配的早餐相关活动
    breakfast_activities_to_assign = [
        {"name": "帮助老年人进食、进水", "id": "5"},
        {"name": "老年人进食、水种类和量的观察与记录", "id": "3"}
    ]

    # 找出7:00-8:40时间范围内的所有时间段
    breakfast_slots = []
    for slot_info in time_slot_info:
        slot_time_str = slot_info["time_slot_str"]
        start_hour = slot_info["start_hour"]
        start_minute = slot_info["start_minute"]

        # 计算小时数（带小数）
        hour_decimal = start_hour + start_minute / 60

        # 判断是否在7:00-8:40范围内
        if 7.0 <= hour_decimal < 8.67 and slot_time_str not in sleep_time_slots:
            # 不排除用餐时间段，但在日志中记录
            if slot_time_str in meal_time_slots:
                logger.info(f"时间段 {slot_time_str} 是用餐时间段，但仍然添加到早餐时间段列表中")
            breakfast_slots.append(slot_time_str)

    # 如果找到了足够的时间段，随机分配活动
    if len(breakfast_slots) >= len(breakfast_activities_to_assign):
        # 随机打乱时间段列表
        random.shuffle(breakfast_slots)

        # 为每个活动分配一个时间段
        for i, activity in enumerate(breakfast_activities_to_assign):
            activity_slot = breakfast_slots[i]

            # 匹配护理员
            matched_caregivers = []
            for caregiver in caregivers:
                # 解析护理员技能
                caregiver_skills = []
                if caregiver.skills:
                    caregiver_skills = [
                        skill.strip()
                        for skill in caregiver.skills.split(",")
                        if skill.strip()
                    ]

                # 这些活动不需要特定技能
                if caregiver_skills:
                    matched_caregivers.append(caregiver)
                    logger.info(f"护理员 {caregiver.attendant_name} 匹配通用技能")

            if matched_caregivers:
                # 根据工作负荷选择护理员
                matched_caregivers.sort(key=lambda c: caregiver_workload[c.id])
                selected_caregiver = matched_caregivers[0]

                # 更新护理员工作负荷
                caregiver_workload[selected_caregiver.id] += 1

                # 将活动添加到映射中，覆盖原有活动
                timeline_map[activity_slot] = {
                    "Activity": activity["name"],
                    "TimeSlot": activity_slot,
                    "Caregiver": selected_caregiver.attendant_name,
                    "ActivityId": activity["id"],
                    "CaregiverId": selected_caregiver.id
                }

                logger.info(f"在7:00-8:40时间范围内分配活动 {activity['name']} (ID: {activity['id']}) 到时间段 {activity_slot}，护理员: {selected_caregiver.attendant_name}")
            else:
                # 没有匹配的护理员，使用lack
                timeline_map[activity_slot] = {
                    "Activity": activity["name"],
                    "TimeSlot": activity_slot,
                    "Caregiver": "lack",
                    "ActivityId": activity["id"],
                    "CaregiverId": "-1"
                }

                logger.info(f"在7:00-8:40时间范围内分配活动 {activity['name']} (ID: {activity['id']}) 到时间段 {activity_slot}，护理员: lack")
    else:
        logger.warning(f"在7:00-8:40时间范围内找到的时间段数量 ({len(breakfast_slots)}) 不足以分配所有指定活动 ({len(breakfast_activities_to_assign)})")

    # 更新照护时间线
    updated_timeline = []
    for time_slot_str in time_slot_list:
        if time_slot_str in timeline_map:
            updated_timeline.append(timeline_map[time_slot_str])
        else:
            # 没有该时间段的活动，使用None
            updated_timeline.append({
                "TimeSlot": time_slot_str,
                "Activity": "None",
                "ActivityId": "0",
                "Caregiver": "None",
                "CaregiverId": "0"
            })

    return updated_timeline

def add_ward_rounds(care_timeline, time_slot_list, sleep_time_slots, meal_time_slots):
    """为照护计划添加查房活动

    Args:
        care_timeline: 照护时间线
        time_slot_list: 时间段列表
        sleep_time_slots: 睡眠时间段列表
        meal_time_slots: 用餐时间段列表

    Returns:
        更新后的照护时间线
    """
    import random
    from config_params import three_shift_params

    logger.info("开始为照护计划添加查房活动...")

    # 检查是否需要隐藏未分配活动
    hide_unassigned = three_shift_params.get("hide_unassigned_activities", False)

    # 查房活动信息
    ward_round_name = "查房"
    ward_round_id = "178"  # 确保使用正确的ID

    # 将时间段分为白天和晚上
    day_slots = []
    night_slots = []

    # 创建时间段与照护时间线条目的映射
    timeline_map = {entry["TimeSlot"]: entry for entry in care_timeline}

    # 分类时间段
    for time_slot in time_slot_list:
        # 解析时间段
        start_time = time_slot.split("-")[0]
        hour = int(start_time.split(":")[0])

        # 跳过用餐时间段
        if time_slot in meal_time_slots:
            continue

        # 判断是否是晚上时间段（22:00-06:00）
        is_night = (hour >= 22) or (hour < 6)

        # 获取当前时间段的照护条目
        entry = timeline_map.get(time_slot)
        if not entry:
            continue

        # 如果启用了隐藏未分配活动的功能，跳过未分配护理员的时间段
        if hide_unassigned and entry["Caregiver"] == "None":
            continue

        # 白天：只有在没有老人需求时才能添加查房
        # 晚上：可以覆盖睡眠时间段，但要确保优先满足老人的特定需求
        if (not is_night and (entry["Activity"] == "None" or entry["ActivityId"] == "0" or entry["Activity"] == "老年人照护活动")) or \
           (is_night and (entry["Activity"] == "None" or entry["ActivityId"] == "0" or entry["Activity"] == "老年人照护活动" or \
                         (entry["Activity"] == "老年人睡眠状况观察记录" and entry["ActivityId"] == "17"))):
            # 可以添加查房的时间段
            if is_night:
                night_slots.append(time_slot)
                logger.info(f"晚上时间段 {time_slot} 可以进行查房，活动: {entry['Activity']}, 活动ID: {entry['ActivityId']}")
            else:
                day_slots.append(time_slot)
                logger.info(f"白天时间段 {time_slot} 可以进行查房，活动: {entry['Activity']}, 活动ID: {entry['ActivityId']}")

    # 随机选择一个白天时间段和一个晚上时间段进行查房
    selected_slots = []

    # 白天查房
    if day_slots:
        # 优先选择"None"或"0"的时间段
        empty_slots = [slot for slot in day_slots if timeline_map.get(slot, {}).get("Activity") == "None" or timeline_map.get(slot, {}).get("ActivityId") == "0"]
        if empty_slots:
            day_slot = random.choice(empty_slots)
        else:
            day_slot = random.choice(day_slots)
        selected_slots.append(day_slot)
        logger.info(f"选择白天时间段 {day_slot} 进行查房")
    else:
        logger.warning("没有可用的白天时间段进行查房")
        # 如果没有找到合适的白天时间段，尝试在其他时间段中选择
        other_day_slots = []
        for time_slot in time_slot_list:
            start_time = time_slot.split("-")[0]
            hour = int(start_time.split(":")[0])
            if (6 <= hour < 22) and time_slot not in meal_time_slots:
                other_day_slots.append(time_slot)

        if other_day_slots:
            day_slot = random.choice(other_day_slots)
            selected_slots.append(day_slot)
            logger.info(f"在其他白天时间段中选择 {day_slot} 进行查房")
        else:
            logger.error("无法找到任何白天时间段进行查房")

    # 晚上查房
    if night_slots:
        # 优先选择"None"或"0"的时间段
        empty_slots = [slot for slot in night_slots if timeline_map.get(slot, {}).get("Activity") == "None" or timeline_map.get(slot, {}).get("ActivityId") == "0"]
        if empty_slots:
            night_slot = random.choice(empty_slots)
        else:
            night_slot = random.choice(night_slots)
        selected_slots.append(night_slot)
        logger.info(f"选择晚上时间段 {night_slot} 进行查房")
    else:
        logger.warning("没有可用的晚上时间段进行查房")
        # 如果没有找到合适的晚上时间段，尝试在睡眠时间段中选择
        sleep_night_slots = []
        for time_slot in time_slot_list:
            start_time = time_slot.split("-")[0]
            hour = int(start_time.split(":")[0])
            if ((hour >= 22) or (hour < 6)) and time_slot not in meal_time_slots:
                entry = timeline_map.get(time_slot)
                if entry and entry.get("Activity") == "老年人睡眠状况观察记录" and entry.get("ActivityId") == "17":
                    sleep_night_slots.append(time_slot)

        if sleep_night_slots:
            night_slot = random.choice(sleep_night_slots)
            selected_slots.append(night_slot)
            logger.info(f"在睡眠时间段中选择 {night_slot} 进行查房")
        else:
            logger.error("无法找到任何晚上时间段进行查房")

    # 更新照护时间线
    for time_slot in selected_slots:
        # 获取当前时间段的照护条目
        entry = timeline_map.get(time_slot)
        if not entry:
            continue

        # 保留原来的护理员信息
        caregiver_name = entry["Caregiver"]
        caregiver_id = entry["CaregiverId"]

        # 如果没有分配护理员，使用lack
        if caregiver_name == "None" or caregiver_id == "0":
            # 如果启用了隐藏未分配活动的功能，跳过未分配护理员的时间段
            if hide_unassigned:
                logger.info(f"跳过未分配护理员的查房时间段: {time_slot}")
                continue
            caregiver_name = "lack"
            caregiver_id = "-1"

        # 记录原始活动信息
        original_activity = entry["Activity"]
        original_activity_id = entry["ActivityId"]

        # 更新照护条目
        entry["Activity"] = remove_leading_number(ward_round_name)
        entry["ActivityId"] = ward_round_id
        entry["Caregiver"] = caregiver_name
        entry["CaregiverId"] = caregiver_id

        logger.info(f"在时间段 {time_slot} 添加查房活动，替代原活动: {original_activity} (ID: {original_activity_id})，护理员: {caregiver_name}")

    logger.info(f"查房活动添加完成，共添加 {len(selected_slots)} 个查房活动")

    return care_timeline

# 在应用启动时应用修复
apply_fix_to_three_shift()
